/*
 * Copyright (c) 2020 hebeiyiliuba.com
 * All rights reserved.
 *
 */

package org.jeecg.modules.wlhy.report.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.Throw;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ReportPlatformEnum;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.LngLonUtil;
import org.jeecg.modules.third.jg.report.freight.information.constant.enums.ReportDocTypeEnum;
import org.jeecg.modules.third.jg.report.freight.information.dto.AppInfoDTO;
import org.jeecg.modules.third.jg.report.freight.information.service.TianjinReportPlatformService;
import org.jeecg.modules.third.jg.report.information.constant.enums.PaymentMeansCodeEnum;
import org.jeecg.modules.third.jg.report.information.dto.DriverDTO;
import org.jeecg.modules.third.jg.report.information.dto.ReqHeaderDTO;
import org.jeecg.modules.third.jg.report.information.dto.ResultDTO;
import org.jeecg.modules.third.jg.report.information.dto.VehicleDTO;
import org.jeecg.modules.third.jg.report.information.dto.enterprise.AppsDTO;
import org.jeecg.modules.third.jg.report.information.dto.enterprise.EnterpriseDTO;
import org.jeecg.modules.third.jg.report.information.dto.financial.FinancialDTO;
import org.jeecg.modules.third.jg.report.information.dto.financial.FinanciallistDTO;
import org.jeecg.modules.third.jg.report.information.dto.financial.ShippingNoteListDTO;
import org.jeecg.modules.third.jg.report.information.dto.shippingnote.*;
import org.jeecg.modules.third.jg.report.information.service.ReportInformationService;
import org.jeecg.modules.third.jg.report.information.utils.XmlUtils;
import org.jeecg.modules.wlhy.bill.entity.HyShippingNoteBill;
import org.jeecg.modules.wlhy.bill.service.IHyShippingNoteBillService;
import org.jeecg.modules.wlhy.company.entity.HyCompany;
import org.jeecg.modules.wlhy.company.entity.HyCompanyConfig;
import org.jeecg.modules.wlhy.company.service.IHyCompanyService;
import org.jeecg.modules.wlhy.customer.entity.HyCustomer;
import org.jeecg.modules.wlhy.customer.service.IHyCustomerService;
import org.jeecg.modules.wlhy.customer.service.impl.HyCustomerServiceImpl;
import org.jeecg.modules.wlhy.enterprise.entity.HyEnterprise;
import org.jeecg.modules.wlhy.enterprise.entity.HyEnterpriseApps;
import org.jeecg.modules.wlhy.enterprise.service.IHyEnterpriseService;
import org.jeecg.modules.wlhy.enterprise.service.impl.HyEnterpriseAppsServiceImpl;
import org.jeecg.modules.wlhy.hyconfig.entity.HyConfig;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriver;
import org.jeecg.modules.wlhy.hydriver.entity.HyDriverReport;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverReportService;
import org.jeecg.modules.wlhy.hydriver.service.IHyDriverService;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicle;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleReport;
import org.jeecg.modules.wlhy.hyvehicle.entity.HyVehicleType;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleReportService;
import org.jeecg.modules.wlhy.hyvehicle.service.IHyVehicleService;
import org.jeecg.modules.wlhy.order.entity.HyOrder;
import org.jeecg.modules.wlhy.order.service.IHyOrderService;
import org.jeecg.modules.wlhy.report.IReportService;
import org.jeecg.modules.wlhy.shipping.constant.ShippingPayStatus;
import org.jeecg.modules.wlhy.shipping.entity.HyShippingNote;
import org.jeecg.modules.wlhy.shipping.service.IHyShippingNoteService;
import org.jeecg.modules.wlhy.utils.HyCfgUtil;
import org.jeecg.modules.wlhy.utils.HyConfigUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Description: TODO
 * @author: duanlikao
 * @date: 2022年11月18日 14:17
 */
@Service
@Slf4j
public class TjJgReportService implements IReportService {

    @Resource
    private IHyDriverReportService hyDriverReportService;

    @Resource
    private IHyVehicleReportService vehicleReportService;

    @Resource
    private BaseReportService baseReportService;

    @Autowired
    private IHyCustomerService customerService;

    @Autowired
    private IHyOrderService orderService;

    @Resource
    private HyEnterpriseAppsServiceImpl enterpriseAppsService;

    @Resource
    private TianjinReportPlatformService tianjinReportPlatformService;

    @Resource
    private IHyEnterpriseService enterpriseService;

    @Resource
    private IHyShippingNoteService shippingNoteService;

    @Autowired
    private IHyCompanyService hyCompanyService;

    @Autowired
    private IHyDriverService hyDriverService;

    @Autowired
    private IHyVehicleService hyVehicleService;

    @Autowired
    private IHyShippingNoteBillService shippingNoteBillService;

    @Override
    public ReportPlatformEnum getReportType() {
        return ReportPlatformEnum.REPORT_PLATFORM_TJ;
    }

    @Override
    public void checkReport() {
        //天津监管平台
        if(!HyCfgUtil.isUsed2("tianjin_report")){
            throw new JeecgBootException("天津监管平台未配置参数!");
        }
    }

    @Override
    public Result setReportInfo(HyCompanyConfig hyCompanyConfig) {

        if (StrUtil.isEmpty(hyCompanyConfig.getReportUrl()) || StrUtil.isEmpty(hyCompanyConfig.getReportUsername())
                || StrUtil.isEmpty(hyCompanyConfig.getReportPassword()) || StrUtil.isEmpty(hyCompanyConfig.getReportPublickey())) {
            return Result.error("天津监管平台未配置参数!");
        }

        this.tianjinReportPlatformService.setReportInfo(hyCompanyConfig.getReportUrl(),
                hyCompanyConfig.getReportUsername(),
                hyCompanyConfig.getReportPassword(),
                hyCompanyConfig.getReportPublickey(),
                hyCompanyConfig.getReportAppid(),
                hyCompanyConfig.getReportAppkey(),
                hyCompanyConfig.getReportAppsender(),
                hyCompanyConfig.getReportApprelease());
        return Result.ok("设置成功");
    }

    @Override
    public AppInfoDTO getAppInfo() {
        return tianjinReportPlatformService.getAppInfo();
    }

    @Override
    public boolean report(HyShippingNote hyShippingNote)  {
        return false;
    }

    @Override
    public Result reportShippingNote(HyShippingNote hyShippingNote) {
        Result result = checkDriverAndVehicle(hyShippingNote.getId());
        if (!result.getCode().equals(CommonConstant.SC_OK_200)) {
            return result;
        }

        return this.uploadShippingNote(hyShippingNote);
    }

    @Override
    public Result reportCapitalFlow(HyShippingNote hyShippingNote) {
        Result result = checkDriverAndVehicle(hyShippingNote.getId());
        if (!result.getCode().equals(CommonConstant.SC_OK_200)) {
            return result;
        }

        return this.uploadCapitalFlow(hyShippingNote.getId());
    }

    //上报运单和资金流水前，先确认司机、车辆的上传状态
    private Result checkDriverAndVehicle(String shippingId) {

        HyShippingNote hyShippingNote = this.shippingNoteService.getById(shippingId);
        if (null == hyShippingNote) {
            return Result.error("运单不存在");
        }

        String driverId = hyShippingNote.getDriverId();
        String vehicleId = hyShippingNote.getVehicleId();
        if (StrUtil.isEmpty(driverId)) {
            return Result.error("当前运单司机信息不存在");
        }

        if (StrUtil.isEmpty(vehicleId)) {
            return Result.error("当前运单车辆信息不存在");
        }

        //自动上报司机和车辆配置
        String autoUpload = HyCfgUtil.getCfgItem2("tianjin_report","auto_upload");

        boolean bDriverUploadStatus = this.hyDriverReportService.checkUploadStatus(driverId, hyShippingNote.getCompanyId(),
                ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
        if (!bDriverUploadStatus) {
            if (StrUtil.isEmpty(autoUpload) || !autoUpload.equals("1")) {
                return Result.error("请先同步司机数据");
            }
            log.warn("司机未上报天津监管，开始同步司机数据, {}", driverId);
            Result dResult = this.reportDriver(driverId, hyShippingNote.getCompanyId());
            if (!dResult.getCode().equals(CommonConstant.SC_OK_200)) {
                return dResult;
            }
        }

        boolean bVehicleUploadStatus = this.vehicleReportService.checkUploadStatus(vehicleId, hyShippingNote.getCompanyId(),
                ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
        if (!bVehicleUploadStatus) {
            if (StrUtil.isEmpty(autoUpload) || !autoUpload.equals("1")) {
                return Result.error("请先同步车辆数据");
            }
            log.warn("车辆未上报天津监管，开始同步车辆数据, {}", vehicleId);
            Result vResult = this.reportVehicle(vehicleId, hyShippingNote.getCompanyId());
            if (!vResult.getCode().equals(CommonConstant.SC_OK_200)) {
                return vResult;
            }
        }

        return Result.OK();
    }

    /**
     * 获取两个日期相差的小时数
     *
     * @param
     * @param
     */
    public static int getDayBetweenTwoDate(Date startDate, Date endDate) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int days = 0;
//            Date startDate = simpleDateFormat.parse(startDateStr);
//            Date endDate = simpleDateFormat.parse(endDateStr);
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);
        //计算两个日期相差的天数
        //startCalendar.getTime().getTime()返回long毫秒数形式,毫秒转为秒所以除以1000
        //1天=24小时，1小时=60分，1分=60秒，所以两个时间的差再除以60 * 60 * 24换算成天的形式
        days = ((int) (startCalendar.getTime().getTime() / 1000) - (int) (endCalendar.getTime().getTime() / 1000)) / (60 * 60 );
        return Math.abs(days);
    }


    /**
     * 司机上报
     * @param driverId
     * @return
     */
    @Override
    public Result reportDriver(String driverId, String companyId){
        HyDriver hyDriverDb = this.hyDriverService.getById(driverId);
        if(hyDriverDb == null) {
            throw new JeecgBootException("未找到对应数据");
        }
        HyDriverReport hyDriverReport = new HyDriverReport();

        //人员从业资格证验证
        if (!this.hyDriverService.checkQualificationV2(hyDriverDb)) {
            throw new JeecgBootException("人员从业资格证验证号不正确或者已过期，请修改后重新上传！");
        }

        DriverDTO driverDTO = hyDriverTODriverDTO(hyDriverDb);
        ReqHeaderDTO reqHeaderDTO = new ReqHeaderDTO();
        reqHeaderDTO.setDriver(driverDTO);
        String xmlString = XmlUtils.converTomXml(reqHeaderDTO);

        try {
            ResultDTO reportResult = this.tianjinReportPlatformService.sendReport(ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_JSY, xmlString);

            //hyDriverReport.setId(driverId);
            hyDriverReport.setDriverId(driverId);
            hyDriverReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
            hyDriverReport.setCompanyId(companyId);
            if (null != reportResult) {
                hyDriverReport.setDriverUploadStatus(reportResult.getCode().equals("00000") ? "1" : "2");
                hyDriverReport.setDriverReportFailureReason(reportResult.getErrorMessage());
                hyDriverReport.setUploadDate(new Date());
            } else {
                hyDriverReport.setDriverUploadStatus("2");
                hyDriverReport.setUploadDate(new Date());
                hyDriverReport.setDriverReportFailureReason("监管上报系统接口异常,联系管理员检查");
                return Result.error("天津上报司机数据发生错误");
            }
            this.hyDriverReportService.saveDriverReport(hyDriverReport);
            boolean bUpdate = this.hyDriverService.updateJgUploadStatusById(driverId, hyDriverReport.getDriverUploadStatus());
            log.info("天津监管更新司机上报回执信息, {}, {}", bUpdate, reportResult.getErrorMessage());

            return reportResult.getCode().equals("00000") ? Result.OK("上报成功") : Result.error(reportResult.getErrorMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("天津上报司机数据过程发生错误, {}", e.getMessage());
        }

        return Result.error("天津上报司机数据失败");
    }

    private DriverDTO hyDriverTODriverDTO(HyDriver hyDriver) {
        if (hyDriver == null) {
            return null;
        }
        DriverDTO driverDTO = new DriverDTO();
        driverDTO.setDriverName(hyDriver.getDriverName());
        driverDTO.setDrivingLicense(hyDriver.getDrivingLicense());
        driverDTO.setVehicleClass(hyDriver.getVehicleClass());
        driverDTO.setQualificationCertificate(
                StrUtil.isNotEmpty(hyDriver.getQualificationCertificate()) ? hyDriver.getQualificationCertificate() : hyDriver.getDrivingLicense()
        );
        driverDTO.setIssuingOrganizations(hyDriver.getIssuingOrganizations());
        driverDTO.setValidPeriodFrom(
                DateUtils.dateToStringNoBar(hyDriver.getValidPeriodFrom())
        );
        driverDTO.setValidPeriodTo(
                DateUtils.dateToStringNoBar(hyDriver.getValidPeriodTo())
        );
        driverDTO.setTelephone(hyDriver.getTelephone());
        return driverDTO;
    }

    /**
     * 上报车辆
     * @param vehicleId
     * @return
     */
    @Override
    public Result reportVehicle(String vehicleId, String companyId) {

        HyVehicle hyVehiclDb = this.hyVehicleService.getById(vehicleId);
        if (null == hyVehiclDb) {
            throw new JeecgBootException("未找到对应数据");
        }

        HyVehicleReport hyVehicleReport = new HyVehicleReport();

        if (StrUtil.isEmpty(hyVehiclDb.getRoadTransportNumber())) {
            throw new JeecgBootException("车辆道路运输证不能为空！");
        }
        //车辆道路运输证号 中交检查
        if (!hyVehicleService.checkRTCNoV2(hyVehiclDb)) {
            throw new JeecgBootException("车辆道路运输证号不正确或者已过期，请修改后重新上传！");
        }

        HyVehicleType hyVehicleType = this.hyVehicleService.getHyVehicleType(hyVehiclDb.getVehicleType());
        if (hyVehicleType == null) {
            throw new JeecgBootException("车辆类型不存在,请修改后重新上传！");
        }

        hyVehiclDb.setVehicleType(hyVehicleType.getValue());

        VehicleDTO vehicleDTO = vehicleDTOTODriverDTO(hyVehiclDb);
        ReqHeaderDTO reqHeaderDTO = new ReqHeaderDTO();
        reqHeaderDTO.setVehicle(vehicleDTO);
        String xmlString = XmlUtils.converTomXml(reqHeaderDTO);

        try {
            ResultDTO reportResult = this.tianjinReportPlatformService.sendReport(ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_CL, xmlString);

            //hyVehicleReport.setId(vehicleId);
            hyVehicleReport.setVehicleId(vehicleId);
            hyVehicleReport.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
            hyVehicleReport.setCompanyId(companyId);
            if(null != reportResult){
                hyVehicleReport.setVehicleUploadStatus(reportResult.getCode().equals("00000") ? "1" : "2");
                hyVehicleReport.setUploadDate( new Date() );
                hyVehicleReport.setVehicleReportFailureReason(reportResult.getErrorMessage());
            } else {
                hyVehicleReport.setVehicleUploadStatus("2");
                hyVehicleReport.setUploadDate( new Date() );
                hyVehicleReport.setVehicleReportFailureReason("监管上报系统接口异常,联系管理员检查");
                return Result.error("上报车辆数据发生错误");
            }
            vehicleReportService.saveVehicleReport(hyVehicleReport);
            boolean bUpdate = this.hyVehicleService.updateJgUploadStatusById(vehicleId, hyVehicleReport.getVehicleUploadStatus());
            log.info("天津监管更新车辆上报回执信息, {}, {}", bUpdate, reportResult.getErrorMessage());

            return reportResult.getCode().equals("00000") ? Result.OK("上报成功") : Result.error(reportResult.getErrorMessage());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("天津上报司机数据过程发生错误, {}", e.getMessage());
        }

        return Result.error("天津上报车辆数据失败");
    }

    private static VehicleDTO vehicleDTOTODriverDTO(HyVehicle hyVehicle) {
        if (hyVehicle == null) {
            return null;
        }
        VehicleDTO vehicleDTO = new VehicleDTO();
        vehicleDTO.setVehicleNumber(hyVehicle.getVehicleNumber());
        vehicleDTO.setVehiclePlateColorCode(hyVehicle.getVehiclePlateColorCode());
        vehicleDTO.setVehicleType(hyVehicle.getVehicleType());
        vehicleDTO.setOwner(hyVehicle.getOwner());
        vehicleDTO.setUseCharacter(hyVehicle.getUseCharacter());
        vehicleDTO.setVin(hyVehicle.getVin());
        vehicleDTO.setIssuingOrganizations(hyVehicle.getIssuingOrganizations());
        vehicleDTO.setRegisterDate(DateUtils.dateToStringNoBar(hyVehicle.getRegisterDate()));
        vehicleDTO.setIssueDate(DateUtils.dateToStringNoBar(hyVehicle.getIssueDate()));
        vehicleDTO.setVehicleEnergyType(hyVehicle.getVehicleEnergyType());
        vehicleDTO.setVehicleTonnage(
                hyVehicle.getVehicleTonnage() != null ?  hyVehicle.getVehicleTonnage()
                        .setScale(2, BigDecimal.ROUND_DOWN).toString() :"40.00"
        );
        vehicleDTO.setGrossMass(
                hyVehicle.getGrossMass() != null ?  hyVehicle.getGrossMass()
                        .setScale(2,BigDecimal.ROUND_DOWN).toString() : "48.00"
        );
        vehicleDTO.setRoadTransportCertificateNumber(hyVehicle.getRoadTransportNumber());

        return vehicleDTO;
    }

    /**
     * 天津省平台上报企业信息
     * @param actionType 操作类型  1:新增操作 2：更新操作
     * @return
     */
    public ResultDTO uploadEnterprise(String actionType) {
        HyEnterprise hyEnterprise = this.enterpriseService.queryTopData();
        String xmlString = "";
        EnterpriseDTO enterpriseDTO = enterpriseTOEnterpriseDTO(hyEnterprise,actionType);
        if(enterpriseDTO != null){
            List<AppsDTO> apps = new ArrayList<>();
            QueryWrapper<HyEnterpriseApps> queryWrapper = new QueryWrapper();
            queryWrapper.eq("iz_used",1);
            List <HyEnterpriseApps> enterpriseApps = this.enterpriseAppsService.list(queryWrapper);
            if(CollUtil.isNotEmpty(enterpriseApps)){
                for(HyEnterpriseApps enterpriseApp : enterpriseApps){
                    AppsDTO appsDTO = new AppsDTO();
                    appsDTO.setAppId(enterpriseApp.getAppId());
                    appsDTO.setAppName(enterpriseApp.getAppName());
                    appsDTO.setAppSecurity(enterpriseApp.getAppSecurity());
                    appsDTO.setAppType(enterpriseApp.getAppType());
                    apps.add(appsDTO);
                }
            }
            enterpriseDTO.setApps(apps);
            ReqHeaderDTO reqHeaderDTO= new ReqHeaderDTO();
            reqHeaderDTO.setEnterprise(enterpriseDTO);
            xmlString = XmlUtils.converTomXml(reqHeaderDTO);
        }

        try {
            ResultDTO reportResult = this.tianjinReportPlatformService.sendReport(ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_QY, xmlString);
            return reportResult;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("天津上报企业信息失败");
        }

        return null;
    }

    private static EnterpriseDTO enterpriseTOEnterpriseDTO(HyEnterprise hyEnterprise,String actionType) {
        if (hyEnterprise == null) {
            return null;
        }
        EnterpriseDTO enterpriseDTO = new EnterpriseDTO();
        //操作类型  1:新增操作 2：更新操作
        enterpriseDTO.setActionType(actionType);
        enterpriseDTO.setEntName(hyEnterprise.getEntName());
        enterpriseDTO.setUnifiedSocialCreditIdentifier(hyEnterprise.getUnifiedSocialCreditIdentifier());
        enterpriseDTO.setEntAddress(hyEnterprise.getEntAddress());
        enterpriseDTO.setAreaCode(hyEnterprise.getAreaCode());
        enterpriseDTO.setRegisterMoney(hyEnterprise.getRegisterMoney());
        enterpriseDTO.setRegisterDate(
                DateUtils.dateToStringNoBar(hyEnterprise.getRegisterDate())
        );
        enterpriseDTO.setRunScope(hyEnterprise.getRunScope());
        enterpriseDTO.setPermitNumber(hyEnterprise.getPermitNumber());
        enterpriseDTO.setFaxNo(hyEnterprise.getFaxNo());
        enterpriseDTO.setLegalerName(hyEnterprise.getLegalerName());
        enterpriseDTO.setLegalerTel(hyEnterprise.getLegalerTel());
        enterpriseDTO.setContactsName(hyEnterprise.getContactsName());
        enterpriseDTO.setContactsTel(hyEnterprise.getContactsTel());
        //监测状态  监测状态：0：未开启；1：联调测试开启；2：正式监测开启
        enterpriseDTO.setMonitorsState(hyEnterprise.getMonitorsState());
        enterpriseDTO.setMonitorTime(
                DateUtils.dateToStringDateTime(hyEnterprise.getMonitorTime())
        );
        enterpriseDTO.setEnterpriseCreateTime(
                DateUtils.dateToStringNoBar(hyEnterprise.getEnterpriseCreateTime())
        );
        enterpriseDTO.setIpcNum(hyEnterprise.getIpcnum());
        enterpriseDTO.setPsnrnum(hyEnterprise.getPsnrnum());
        return enterpriseDTO;
    }

    /**
     * 天津省平台上报电子运单
     * @param hyShippingNote
     * @return
     */
    public Result uploadShippingNote(HyShippingNote hyShippingNote) {
        HyShippingNote ShippingNoteDb = shippingNoteService.getById(hyShippingNote.getId());
        if(null == ShippingNoteDb) {
            return Result.error("未找到对应数据");
        }

        if (!ShippingNoteDb.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成");
        }

        try {
            int dayBetweenTwoDate = getDayBetweenTwoDate(hyShippingNote.getPayDt(), new Date());
            if (dayBetweenTwoDate > 23) {
                hyShippingNote.setUploadStatus("2");
                hyShippingNote.setReportFailureReason("单证未及时上传（运单完结时间与市监测平台中运单接入时间相差超过24小时）");
                hyShippingNote.setUploadDate(new Date());
                hyShippingNote.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                shippingNoteService.updateById(hyShippingNote);
                return Result.error("单证未及时上传（运单完结时间与市监测平台中运单接入时间相差超过24小时");
            }
        } catch(ParseException e) {
            e.printStackTrace();
            return Result.error("运单完结时间解析错误");
        }

        HyVehicle hyVehicle = this.hyVehicleService.getById(hyShippingNote.getVehicleId());
        if (null == hyVehicle) {
            throw new JeecgBootException("该运单车辆信息不能为空");
        }

        if (hyShippingNote.getGoodsWeightLoading().compareTo(hyVehicle.getVehicleTonnage()) > 0) {
            hyShippingNote.setUploadStatus("2");
            hyShippingNote.setUploadDate(new Date());
            hyShippingNote.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
            hyShippingNote.setReportFailureReason("货物质量超过车辆核定载质量货物质量:" + hyShippingNote.getGoodsWeightLoading() + "车辆核定载质量:" + hyVehicle.getVehicleTonnage());
            shippingNoteService.updateById(hyShippingNote);
            throw new JeecgBootException("货物质量超过车辆核定载质量货物质量:" + hyShippingNote.getGoodsWeightLoading() + "车辆核定载质量:" + hyVehicle.getVehicleTonnage());
        }

        ShippingNoteDb.setCompanyId(hyShippingNote.getCompanyId());
        ShippingNoteDTO shippingNoteDTO = shippingNoteTOShippingNoteDTO(ShippingNoteDb);
        ReqHeaderDTO reqHeaderDTO = new ReqHeaderDTO();
        reqHeaderDTO.setShippingNote(shippingNoteDTO);
        String xmlString = XmlUtils.converTomXml(reqHeaderDTO);

        try {
            ResultDTO reportResult = this.tianjinReportPlatformService.sendReport(ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_YD, xmlString);
            if (null != reportResult) {
                hyShippingNote.setUploadStatus(reportResult.getCode().equals("00000") ? "1" : "2");
                hyShippingNote.setUploadDate(new Date());
                hyShippingNote.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                hyShippingNote.setReportFailureReason(reportResult.getErrorMessage());
                shippingNoteService.updateById(hyShippingNote);
            } else {
                hyShippingNote.setUploadStatus("2");
                hyShippingNote.setUploadDate(new Date());
                hyShippingNote.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                hyShippingNote.setReportFailureReason("监管上报系统接口异常,联系管理员检查");
                shippingNoteService.updateById(hyShippingNote);
                return Result.error("天津上报运单数据发生错误");
            }

            return reportResult.getCode().equals("00000") ? Result.OK("上报成功") : Result.error(reportResult.getErrorMessage());
        } catch (Exception e) {
            hyShippingNote.setUploadStatus("2");
            hyShippingNote.setReportFailureReason(e.getMessage());
            hyShippingNote.setUploadDate(new Date());
            hyShippingNote.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
            shippingNoteService.updateById(hyShippingNote);
            e.printStackTrace();
            log.error("天津上报运单数据发生错误{}", e.getMessage());
        }

        return Result.error("天津上报运单失败");
    }

    /**
     * 组装电子运单报文
     * @param hyShippingNote
     * @return
     */
    private  ShippingNoteDTO shippingNoteTOShippingNoteDTO(HyShippingNote hyShippingNote) {
        if (hyShippingNote == null) {
            throw new JeecgBootException("该运单上报数据不能为空");
        }

        HyCustomer hyCustomer = this.customerService.getById(hyShippingNote.getCustomerId());
        if(hyCustomer == null){
            throw new JeecgBootException("该运单货主信息不能为空");
        }

        HyOrder hyOrder = this.orderService.getById(hyShippingNote.getOrderId());
        if(hyOrder == null){
            throw new JeecgBootException("该运单货源信息不能为空");
        }

        HyDriver hyDriver = this.hyDriverService.getById(hyShippingNote.getDriverId());
        if(hyDriver == null){
            throw new JeecgBootException("该运单司机信息不能为空");
        }
        HyVehicle hyVehicle = this.hyVehicleService.getById(hyShippingNote.getVehicleId());
        if(hyVehicle == null){
            throw new JeecgBootException("该运单车辆信息不能为空");
        }

        HyCompany company = this.hyCompanyService.getById(hyShippingNote.getCompanyId());
        if (null == company) {
            throw new JeecgBootException("该运单公司信息不能为空");
        }

        ShippingNoteDTO shippingNoteDTO = new ShippingNoteDTO();

        shippingNoteDTO.setOriginalDocumentNumber(hyOrder.getOrderNum());
        String shippingNoteNumber = hyShippingNote.getShippingNoteNumber().replaceAll("-","");
        if(shippingNoteNumber.length() > 20 ){
            shippingNoteNumber =  shippingNoteNumber.substring(0, 20);
        }
        shippingNoteDTO.setShippingNoteNumber(shippingNoteNumber);

        //Integer vehicleAmounthy = getVehicleAmounthyByOrderId(hyShippingNote.getOrderId()) ;
        shippingNoteDTO.setVehicleAmount(1);
        //分段分单号 分段运输和多车运输由 四位数字组成， 前两位代表一 单多车的序号，后两位代表分 段序号。
        //若运输形式为一单一 车填 0000。
        shippingNoteDTO.setSerialNumber("0000");
        //运输组织类型代码
        shippingNoteDTO.setTransportTypeCode(1);
        shippingNoteDTO.setSendToProDateTime(
                DateUtils.dateToStringDateTime(new Date())
        );

        shippingNoteDTO.setCarrier(company.getCompanyName());
        shippingNoteDTO.setUnifiedSocialCreditIdentifier(company.getCreditCode());
        //道路运输经营许可证编号 车辆道路运输经营许可 网络货运经营者的 道路运输经营许可证编号。
        shippingNoteDTO.setPermitNumber(company.getPermitNumber());
        if (StrUtil.isEmpty(company.getCreditCode()) || StrUtil.isEmpty(company.getPermitNumber())) {
            throw new JeecgBootException("上报公司的[统一社会信用代码]或[道路运输经营许可证编码]不能为空");
        }

        shippingNoteDTO.setConsignmentDateTime(
                DateUtils.dateToStringDateTime(hyShippingNote.getCreateTime())
        );
        shippingNoteDTO.setBusinessTypeCode(hyShippingNote.getBusinessTypeCode());

        shippingNoteDTO.setDespatchActualDateTime(
                DateUtils.dateToStringDateTime(hyShippingNote.getStatusDtLoading())
        );
        shippingNoteDTO.setGoodsReceiptDateTime(
                DateUtils.dateToStringDateTime(hyShippingNote.getStatusDtUnloading())
        );
        BigDecimal costPayShipping = hyShippingNote.getDriverFee() ;


        shippingNoteDTO.setTotalMonetaryAmount(
                costPayShipping.setScale(3, BigDecimal.ROUND_DOWN).toString()
        );

        BigDecimal gasAmount = BigDecimal.ZERO;
        if(!"0".equals(hyShippingNote.getIzUsedGas())) {
            gasAmount = hyShippingNote.getGasRechargeAmount();
        }

        shippingNoteDTO.setTransportationCost(
                gasAmount.setScale(3, BigDecimal.ROUND_DOWN).toString()
        );
        double m =  LngLonUtil.GetDistance( hyShippingNote.getSendLatitude(), hyShippingNote.getSendLongitude(),
                hyShippingNote.getReceiveLatitude(),hyShippingNote.getReceiveLongitude());
        double km =  m > 0d ? Math.round((m/100d)/10d) : 0d;
        int distance = 0;
        if (StrUtil.isNotEmpty(hyShippingNote.getTransportationDistance())) {
            distance = Double.valueOf(hyShippingNote.getTransportationDistance()).intValue();
        }
        if (distance > 0) {
            shippingNoteDTO.setTransportationDistance(String.valueOf(distance));
        } else {
            shippingNoteDTO.setTransportationDistance(String.valueOf((int)Math.round(km)));
        }

        shippingNoteDTO.setFinishDateTime(
                DateUtils.dateToStringDateTime(hyShippingNote.getPayDt())
        );

        //托运人信息
        getConsignorInfo(hyCustomer, hyShippingNote, shippingNoteDTO);
        //收货方信息
        getConsigneeInfo(hyShippingNote, shippingNoteDTO);
        //车辆信息
        getVehicleInfo(hyShippingNote,  hyDriver, hyVehicle, shippingNoteDTO);
        //实际承运人信息
        getActualCarrierInfo(hyVehicle,hyDriver,  shippingNoteDTO);
        //保险信息
        getInsuranceInformation(shippingNoteDTO);

        return shippingNoteDTO;
    }

    /**
     * 保险信息
     * @param shippingNoteDTO
     */
    private void getInsuranceInformation(ShippingNoteDTO shippingNoteDTO) {
        InsuranceInformation insuranceInformation = new InsuranceInformation();
        insuranceInformation.setInsuranceCompanyCode("none");
        insuranceInformation.setPolicyNumber("none");
        shippingNoteDTO.setInsuranceInformation(insuranceInformation);
    }

    /**
     * 实际承运人信息
     * @param hyVehicle
     * @param hyDriver
     * @param shippingNoteDTO
     */
    private void getActualCarrierInfo(HyVehicle hyVehicle,HyDriver hyDriver,  ShippingNoteDTO shippingNoteDTO) {
        ActualCarrierInfo actualCarrierInfo = new ActualCarrierInfo();
        actualCarrierInfo.setActualCarrierName(hyDriver.getDriverName());
        actualCarrierInfo.setActualCarrierBusinessLicense(
                StrUtil.isNotBlank(hyVehicle.getBusinessLicense()) ? hyVehicle.getBusinessLicense() :
                        hyVehicle.getRoadTransportNumber().substring(0 , 6) +"000000"
                //hyVehicle.getRoadTransportNumber()
        );
        actualCarrierInfo.setActualCarrierId(hyDriver.getIdcard());
        shippingNoteDTO.setActualCarrierInfo(actualCarrierInfo);
    }

    /**
     * 车辆信息
     * @param hyShippingNote
     * @param hyDriver
     * @param hyVehicle
     * @param shippingNoteDTO
     */
    private void getVehicleInfo(HyShippingNote hyShippingNote,  HyDriver hyDriver, HyVehicle hyVehicle,
                                ShippingNoteDTO shippingNoteDTO) {
        VehicleInfo vehicleInfo = new VehicleInfo();
        vehicleInfo.setVehiclePlateColorCode(hyVehicle.getVehiclePlateColorCode());
        vehicleInfo.setVehicleNumber(hyVehicle.getVehicleNumber());
        vehicleInfo.setDespatchActualDateTime(
                DateUtils.dateToStringDateTime( hyShippingNote.getStatusDtLoading())
        );
        vehicleInfo.setGoodsReceiptDateTime(
                DateUtils.dateToStringDateTime( hyShippingNote.getStatusDtUnloading())
        );
        vehicleInfo.setPlaceOfLoading(hyShippingNote.getSendAddress());
        vehicleInfo.setGoodsReceiptPlace(hyShippingNote.getReceiveAddress());
        vehicleInfo.setLoadingCountrySubdivisionCode(hyShippingNote.getSendAreaCode());
        vehicleInfo.setReceiptCountrySubdivisionCode(hyShippingNote.getReceiveAreaCode());
        //司机信息
        getDrivers(hyDriver, vehicleInfo);
        //货物信息
        getGoodsInfos(hyShippingNote, vehicleInfo);
        shippingNoteDTO.setVehicleInfo(vehicleInfo);
    }

    /**
     * 货物信息
     * @param hyShippingNote
     * @param vehicleInfo
     */
    private void getGoodsInfos( HyShippingNote hyShippingNote ,VehicleInfo vehicleInfo) {
        List <GoodsInfo> goodsInfos = new ArrayList <>();
        GoodsInfo goodsInfo = new GoodsInfo();
        goodsInfo.setDescriptionOfGoods(hyShippingNote.getDescriptionOfGoods());
        goodsInfo.setCargoTypeClassificationCode(hyShippingNote.getCargoTypeClassificationCode());
        BigDecimal  goodsWeightLoading =  hyShippingNote.getGoodsWeightLoading().multiply(new BigDecimal("1000"));
        goodsInfo.setGoodsItemGrossWeight(
                goodsWeightLoading.setScale(3, BigDecimal.ROUND_DOWN)
                        .toString()
        );
        goodsInfo.setCube("1.0000");
        goodsInfo.setTotalNumberOfPackages(1);
        goodsInfos.add(goodsInfo);
        vehicleInfo.setGoodsInfo(goodsInfos);
    }

    /**
     * 司机信息
     * @param hyDriver
     * @param vehicleInfo
     */
    private void getDrivers(HyDriver hyDriver, VehicleInfo vehicleInfo) {
        List <DriverDTO> drivers = new ArrayList <>();
        DriverDTO driverDTO= new  DriverDTO();
        driverDTO.setDriverName(hyDriver.getDriverName());
        driverDTO.setDrivingLicense(hyDriver.getDrivingLicense());
        drivers.add(driverDTO);
        vehicleInfo.setDriver(drivers);
    }

    /**
     * 收货方信息
     * @param hyShippingNote
     * @param shippingNoteDTO
     */
    private void getConsigneeInfo(HyShippingNote hyShippingNote, ShippingNoteDTO shippingNoteDTO) {
        ConsigneeInfo consigneeInfo = new ConsigneeInfo();
        consigneeInfo.setConsignee(hyShippingNote.getReceiveContactName());
        consigneeInfo.setConsigneeId("");
        consigneeInfo.setGoodsReceiptPlace(hyShippingNote.getReceiveAddress());
        consigneeInfo.setCountrySubdivisionCode(hyShippingNote.getReceiveAreaCode());
        shippingNoteDTO.setConsigneeInfo(consigneeInfo);
    }

    /**
     * 托运人信息
     * @param hyCustomer
     * @param hyShippingNote
     * @param shippingNoteDTO
     */
    private void getConsignorInfo(HyCustomer hyCustomer, HyShippingNote hyShippingNote, ShippingNoteDTO shippingNoteDTO) {
        ConsignorInfo consignorInfo = new ConsignorInfo();
        consignorInfo.setConsignor(hyCustomer.getCustomerName());
        consignorInfo.setConsignorID(StrUtil.isNotBlank(hyCustomer.getCreditCode()) ? hyCustomer.getCreditCode() : hyCustomer.getIdcard());
        consignorInfo.setPlaceOfLoading(hyShippingNote.getSendAddress());
        consignorInfo.setCountrySubdivisionCode(hyShippingNote.getSendAreaCode());
        shippingNoteDTO.setConsignorInfo(consignorInfo);
    }

//    /**
//     * 根据货源ID有效查询运单数
//     * @param orderId
//     * @return
//     */
//    public int getVehicleAmounthyByOrderId(String orderId){
//        return hyShippingNoteMapper.getVehicleAmounthyByOrderId(orderId);
//    }

    /**
     * 天津运单资金流水单上报
     */
    public Result uploadCapitalFlow(String shippingId){
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("shipping_id", shippingId);

        HyShippingNote hyShippingNote = shippingNoteService.getById(shippingId);
        if (!hyShippingNote.getShippingPayStatus().equals(ShippingPayStatus.支付完成.getValue())) {
            return Result.error("该运单未支付完成");
        }

        if (!"1".equals(hyShippingNote.getUploadStatus())) {
            return Result.error("请先上报运单");
        }

        List<HyShippingNoteBill> shippingNoteBills = shippingNoteBillService.list(queryWrapper);
        if (CollUtil.isEmpty(shippingNoteBills)) {
            return Result.error("未找到对应数据");
        }

        try {
            for(HyShippingNoteBill shippingNoteBill:shippingNoteBills){
                if ("1".equals(shippingNoteBill.getUploadStatus())) {
                    return Result.error("请不要重复上传数据");
                }

                int dayBetweenTwoDate = getDayBetweenTwoDate(shippingNoteBill.getPayDt(), new Date());
                if (dayBetweenTwoDate > 23) {
                    shippingNoteBill.setUploadStatus("2");
                    shippingNoteBill.setReportFailureReason("资金流水单完成支付时间与市监测平台中资金流水单接入时间相差超过24小时");
                    shippingNoteBill.setUploadDate(new Date());
                    shippingNoteBill.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                    shippingNoteBillService.updateById(shippingNoteBill);
                    return Result.error("资金流水单完成支付时间与市监测平台中资金流水单接入时间相差超过24小时");
                }
            }
        } catch(ParseException e) {
            e.printStackTrace();
            return Result.error("资金流水支付时间解析错误");
        }

        FinancialDTO financialDTO = getFinancialDTO(shippingNoteBills,hyShippingNote);
        ReqHeaderDTO reqHeaderDTO= new ReqHeaderDTO();
        reqHeaderDTO.setFinancial(financialDTO);
        String xmlString = XmlUtils.converTomXml(reqHeaderDTO);

        try {
            ResultDTO reportResult = this.tianjinReportPlatformService.sendReport(ReportDocTypeEnum.REPORT_DOC_TYPE_WLHY_JZ, xmlString);
            if (reportResult != null) {
                for (HyShippingNoteBill shippingNoteBill : shippingNoteBills) {
                    shippingNoteBill.setUploadStatus(reportResult.getCode().equals("00000") ? "1" : "2");
                    shippingNoteBill.setUploadDate(new Date());
                    shippingNoteBill.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                    shippingNoteBill.setReportFailureReason(reportResult.getErrorMessage());
                }
            } else {
                for (HyShippingNoteBill shippingNoteBill : shippingNoteBills) {
                    shippingNoteBill.setUploadStatus("2");
                    shippingNoteBill.setUploadDate(new Date());
                    shippingNoteBill.setReportPlatformType(ReportPlatformEnum.REPORT_PLATFORM_TJ.getCode());
                    shippingNoteBill.setReportFailureReason("监管上报系统接口异常,请联系管理员");
                }
            }

            shippingNoteBillService.updateBatchById(shippingNoteBills);
            return reportResult.getCode().equals("00000") ? Result.OK("上报成功") : Result.error(reportResult.getErrorMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return Result.error("天津上报资金流水失败");
    }

    private static FinancialDTO getFinancialDTO(List<HyShippingNoteBill> shippingNoteBills,HyShippingNote hyShippingNote) {
        FinancialDTO financialDTO = new FinancialDTO();
        HyShippingNoteBill  shippingNoteBillDb = shippingNoteBills.get(0);
        financialDTO.setDocumentNumber(shippingNoteBillDb.getBillNum());
        financialDTO.setSendToProDateTime(
                DateUtils.dateToStringDateTime(new Date())
        );
        financialDTO.setCarrier(shippingNoteBillDb.getCarrier());
        financialDTO.setActualCarrierId(shippingNoteBillDb.getActualCarrierId());
        financialDTO.setVehicleNumber(shippingNoteBillDb.getVehicleNumber());
        financialDTO.setVehiclePlateColorCode(shippingNoteBillDb.getVehicleColorCode());

        //运单列表
        List <ShippingNoteListDTO> shippingNoteListDTOS = new ArrayList <>();
        ShippingNoteListDTO shippingNoteListDTO = new ShippingNoteListDTO();

        String shippingNoteNumber = shippingNoteBillDb.getShippingNoteNumber().replaceAll("-","");
        if(shippingNoteNumber.length() > 20 ){
            shippingNoteNumber =  shippingNoteNumber.substring(0, 20);
        }
        shippingNoteListDTO.setShippingNoteNumber(shippingNoteNumber);
        shippingNoteListDTO.setSerialNumber("0000");
        BigDecimal costPayShipping = hyShippingNote.getDriverFee() ;

        shippingNoteListDTO.setTotalMonetaryAmount(
                costPayShipping.setScale(3, BigDecimal.ROUND_DOWN).toString()
        );

        shippingNoteListDTOS.add(shippingNoteListDTO);
        financialDTO.setShippingNoteList(shippingNoteListDTOS);
        //财务列表
        List<FinanciallistDTO>  financiallistDTOS = new ArrayList <>();
        for(HyShippingNoteBill shippingNoteBill : shippingNoteBills){
            FinanciallistDTO financiallistDTO = new FinanciallistDTO();

            financiallistDTO.setPaymentMeansCode(
                    PaymentMeansCodeEnum.PAYMENT_MEANS_TYPE_YHZZ.code
            );
            financiallistDTO.setRecipient(shippingNoteBill.getCarrier());
            financiallistDTO.setReceiptAccount(
                    shippingNoteBill.getCraccno()+shippingNoteBill.getCrlogaccno()
            );
            financiallistDTO.setBankCode(shippingNoteBill.getBankCode());
            financiallistDTO.setSequenceCode(shippingNoteBill.getBillNum());
            financiallistDTO.setMonetaryAmount(
                    shippingNoteBill.getAmt().setScale(3, BigDecimal.ROUND_DOWN).toString()
            );
            financiallistDTO.setDateTime(
                    DateUtils.dateToStringDateTime(shippingNoteBill.getPayDt())
            );

            financiallistDTOS.add(financiallistDTO);
        }

        financialDTO.setFinanciallist(financiallistDTOS);
        return financialDTO;
    }


}
